<?php
/**
 * @package		简易CMS
 * @subpackage	积分处理类
 * @version		$Id: class_credit.php 23 2012-06-11 18:04:03Z htmambo@gmail.com $
 * @author		Hoping
 * @copyright	Copyright (C) 2010 Hoping Software Studio.
 */

class credit {
	var $coef = 1;
	var $extrasql = array();

	function credit() {}

	function &instance() {
		static $object;
		if(empty($object)) {
			$object = new credit();
		}
		return $object;
	}

	function execrule($action, $uid = 0, $needle = '', $coef = 1, $update = 1) {
		global $_G;

		$this->coef = $coef;
		$uid = intval($uid ? $uid : $_G['uid']);
		$rule = $this->getrule($action);
		$updatecredit = false;
		if($rule['credits']) {
			$rulelog = array();
			$rulelog = $this->getrulelog($rule['rid'], $uid);
			if($rule['rewardnum'] && $rule['rewardnum'] < $coef) {
				$coef = $rule['rewardnum'];
			}
			if(empty($rulelog)) {
				$logarr = array(
					'uid' => $uid,
					'rid' => $rule['rid'],
					'total' => $coef,
					'cyclenum' => $coef,
					'dateline' => $_G['timestamp']
				);

				if(in_array($rule['cycletype'], array(2,3))) {
					$logarr['starttime'] = $_G['timestamp'];
				}
				$logarr = $this->addlogarr($logarr, $rule, false);
				if($update) {
					$clid = DB::insert('common_credit_rule_log', $logarr, 1);
					if($rule['norepeat']) {
						$rulelog['isnew'] = 1;
						$rulelog['clid'] = $clid;
						$rulelog['uid'] = $uid;
						$rulelog['norepeat'] = $rule['norepeat'];
						$this->updatecheating($rulelog, $needle, true);
					}
				}
				$updatecredit = true;
			} else {
				$newcycle = false;
				$logarr = array();
				switch($rule['cycletype']) {
					case 0:
						break;
					case 1:
					case 4:
						if($rule['cycletype'] == 1) {
							$today = strtotime(dgmdate($_G['timestamp'], 'Y-m-d'));
							if($rulelog['dateline'] < $today && $rule['rewardnum']) {
								$rulelog['cyclenum'] =  0;
								$newcycle = true;
							}
						}
						if(empty($rule['rewardnum']) || $rulelog['cyclenum'] < $rule['rewardnum']) {
							if($rule['norepeat']) {
								$repeat = $this->checkcheating($rulelog, $needle, $rule['norepeat']);
								if($repeat && !$newcycle) {
									return false;
								}
							}
							if($rule['rewardnum']) {
								$remain = $rule['rewardnum'] - $rulelog['cyclenum'];
								if($remain < $coef) {
									$coef = $remain;
								}
							}
							$cyclenunm = $newcycle ? $coef : 'cyclenum+'.$coef;
							$logarr = array(
								'cyclenum' => "cyclenum=$cyclenunm",
								'total' => 'total=total+'.$coef,
								'dateline' => "dateline='$_G[timestamp]'"
							);
							$updatecredit = true;
						}
						break;

					case 2:
					case 3:
						$nextcycle = 0;
						if($rulelog['starttime']) {
							if($rule['cycletype'] == 2) {
								$start = strtotime(dgmdate($rulelog['starttime'], 'Y-m-d H:00:00'));
								$nextcycle = $start+$rule['cycletime']*3600;
							} else {
								$nextcycle = $rulelog['starttime']+$rule['cycletime']*60;
							}
						}
						if($_G['timestamp'] <= $nextcycle && $rulelog['cyclenum'] < $rule['rewardnum']) {
							if($rule['norepeat']) {
								$repeat = $this->checkcheating($rulelog, $needle, $rule['norepeat']);
								if($repeat && !$newcycle) {
									return false;
								}
							}
							if($rule['rewardnum']) {
								$remain = $rule['rewardnum'] - $rulelog['cyclenum'];
								if($remain < $coef) {
									$coef = $remain;
								}
							}
							$cyclenunm = 'cyclenum+'.$coef;
							$logarr = array(
								'cyclenum' => "cyclenum=cyclenum+$cyclenunm",
								'total' => 'total=total+'.$coef,
								'dateline' => "dateline='$_G[timestamp]'"
							);
							$updatecredit = true;
						} elseif($_G['timestamp'] >= $nextcycle) {
							$newcycle = true;
							$logarr = array(
								'cyclenum' => "cyclenum=$coef",
								'total' => 'total=total+'.$coef,
								'dateline' => "dateline='$_G[timestamp]'",
								'starttime' => "starttime='$_G[timestamp]'",
							);
							$updatecredit = true;
						}
						break;
				}
				if($update) {
					if($rule['norepeat'] && $needle) {
						$this->updatecheating($rulelog, $needle, $newcycle);
					}
					if($logarr) {
						$logarr = $this->addlogarr($logarr, $rule, true);
						DB::query("UPDATE #__common_credit_rule_log SET ".implode(',', $logarr)." WHERE clid='$rulelog[clid]'");
					}
				}

			}

		}
		if($update && ($updatecredit || $this->extrasql)) {
			if(!$updatecredit) {
				$rule['credits'] = 0;
			}
			$this->updatecreditbyrule($rule, $uid, $coef);
		}
		$rule['updatecredit'] = $updatecredit;

		return $rule;
	}

	function lowerlimit($rule, $uid = 0, $coef = 1) {
		global $_G;
		$uid = $uid ? $uid : intval($_G['uid']);
		return true;
	}

	function updatecreditbyrule($rule, $uids = 0, $coef = 1) {
		global $_G;

		$this->coef = intval($coef);
		$uids = $uids ? $uids : intval($_G['uid']);
		$rule = is_array($rule) ? $rule : $this->getrule($rule);
		$creditarr['credits'] = intval($rule['credits']) * $this->coef;
		$creditarr['credits'] = intval($rule['credits']) * $this->coef;
		$this->updatemembercount($creditarr, $uids, is_array($uids) ? false : true, $this->coef > 0 ? urldecode($rule['rulenameuni']) : '');
	}

	function updatemembercount($creditarr, $uids = 0, $checkgroup = true, $ruletxt = '') {
		global $_G;

		if(!$uids) $uids = intval($_G['uid']);
		$uids = is_array($uids) ? $uids : array($uids);
		if($uids && ($creditarr || $this->extrasql)) {
			if($this->extrasql) $creditarr = array_merge($creditarr, $this->extrasql);
			$sql = array();
			if($_G['uid']){
				$uids = array($_G['uid']);
				$creditnotice = $_G['setting']['creditnotice'];
			}
			if($creditnotice) {
				if(!isset($_G['cookiecredits'])) {
					$_G['cookiecredits'] = !empty($_COOKIE['creditnotice']) ? $_COOKIE['creditnotice'][0] : 0;
					$_G['cookiecreditsbase'] = $_G['member']['credits'];
				}
				if($ruletxt) {
					$_G['cookiecreditsrule'] = $ruletxt;
				}
			}
			foreach((array)$creditarr as $key => $value) {
				if(!empty($key)) {
					$value = intval($value);
					$sql[] = "$key=$key+'$value'";
					if($creditnotice) {
						$_G['cookiecredits'] += $value;
					}
				}
			}
			if($creditnotice) {
				dsetcookie('creditnotice', $_G['cookiecredits'].'D'.$_G['uid']);
				if(!empty($_G['cookiecreditsrule'])) {
					dsetcookie('creditrule', strip_tags($_G['cookiecreditsrule']));
				}
			}
			if($sql) {
				DB::query("UPDATE #__common_member SET ".implode(',', $sql)." WHERE uid IN (".dimplode($uids).")", 'UNBUFFERED');
			}
			if($checkgroup && count($uids) == 1) $this->checkusergroup($uids[0]);
			$this->extrasql = array();
		}
	}

	function checkusergroup($uid) {
		global $_G;

		loadcache('usergroups');
		$uid = intval($uid ? $uid : $_G['uid']);
		$groupid = 0;
		if(!$uid) return $groupid;
		if($uid != $_G['uid']) {
			$member = DB::fetch_first("SELECT * FROM #__common_member WHERE uid='$uid'");
		} else {
			$member = $_G['member'];
		}
		if(empty($member)) return $groupid;

		$credits = $member['credits'];
		$updatearray = array();
		$groupid = $member['groupid'];
		$group = $_G['cache']['usergroups'][$member['groupid']];
		if($member['credits'] != $credits) {
			$updatearray['credits'] = $credits;
			$member['credits'] = $credits;
		}
		if(empty($group) || $group['type'] == 'member' && !($member['credits'] >= $group['creditshigher'] && $member['credits'] < $group['creditslower'])) {
			$newgroup = DB::fetch_first("SELECT grouptitle, groupid FROM #__common_usergroup WHERE type='member' AND $member[credits]>=creditshigher AND $member[credits]<creditslower LIMIT 1");
			if(!empty($newgroup)) {
				if($member['groupid'] != $newgroup['groupid']) {
					$updatearray['groupid'] = $groupid = $newgroup['groupid'];
					notification_add($uid, 'system', 'user_usergroup', array(
						'usergroup' => '<a href="index.php?option=member&task=usergroup">'.$newgroup['grouptitle'].'</a>',
					), 1);
				}
			}
		}
		if($updatearray) {
			DB::update('common_member', $updatearray, array('uid' => $uid));
		}

		return $groupid;

	}

	function updatecheating($rulelog, $needle, $newcycle) {
		if($needle) {
			$logarr = array();
			switch($rulelog['norepeat']) {
				case 0:
					break;
				case 1:
					$info = empty($rulelog['info'])||$newcycle ? $needle : $rulelog['info'].','.$needle;
					$logarr['info'] = addslashes($info);
					break;
				case 2:
					$user = empty($rulelog['user'])||$newcycle ? $needle : $rulelog['user'].','.$needle;
					$logarr['user'] = addslashes($user);
					break;
				break;
			}
		}
	}

	function addlogarr($logarr, $rule, $issql = 0) {
		global $_G;
				$credits = intval($rule['credits']) * $this->coef;
				if($issql) {
					$logarr['credits'] = 'credits'."='$credits'";
				} else {
					$logarr['credits'] = $credits;
				}
		return $logarr;
	}

	function getrule($action) {
		global $_G;

		if(empty($action)) {
			return false;
		}
		loadcache('creditrule');
		$rule = false;
		if(is_array($_G['cache']['creditrule'][$action])) {
			$rule = $_G['cache']['creditrule'][$action];
			if(!$rule['rulemenuni']){
				if(strtoupper(CHARSET) != 'UTF-8') {
					$rule['rulenameuni'] = urlencode(diconv($rule['rulename'], CHARSET, 'UTF-8', true));
				} else {
					$rule['rulenameuni'] = urlencode($rule['rulename']);
				}
			}
			$rulenameuni = $rule['rulenameuni'];
			$rule['credits'] = intval($rule['credits']);
		}
		return $rule;
	}

	function getrulelog($rid, $uid = 0) {
		global $_G;

		$log = array();
		$uid = $uid ? $uid : $_G['uid'];
		if($rid && $uid) {
			$query = DB::query("SELECT * FROM #__common_credit_rule_log WHERE uid='$uid' AND rid='$rid'");
			$log = DB::fetch($query);
		}
		return $log;
	}

	function checkcheating($rulelog, $needle, $checktype) {

		$repeat = false;
		switch($checktype) {
			case 0:
				break;
			case 1:
				$infoarr = explode(',', $rulelog['info']);
				if(!empty($rulelog['info']) && in_array($needle, $infoarr)) {
					$repeat = true;
				}
				break;
			case 2:
				$userarr = explode(',', $rulelog['user']);
				if(!empty($rulelog['user']) && in_array($needle, $userarr)) {
					$repeat = true;
				}
				break;
		}
		return $repeat;
	}
}
